<script setup lang="ts">
	import { useBarAction } from '@/hooks/useBarComps';
	import { Message } from '@arco-design/web-vue';
	import { map } from 'lodash-es';
	import NoteAdd from '@/views/note/detail/NoteAdd.vue';
	import { useCompRef, useUploadFile } from '@/hooks/useComp';
	import { ApiNoteBookInfo, ApiNoteBookUpdate } from '@/api/note/noteBook';
	import type { NoteBookDetailEntity, NoteEntity } from '@/entity/note/NoteEntity';
	import { ApiNoteList } from '@/api/note/note';
	import { FILE_PREVIEW } from '@/enums/appEnum';
	import { ApiUpload } from '@/api/common';
	import { fileToFormData } from '@/utils/utils';
	import { useInfiniteScroll, useThrottleFn } from '@vueuse/core';

	const router = useRouter();

	const id = router.currentRoute.value.params?.id as string;

	provide('groupId', id);

	const detail = ref<NoteBookDetailEntity>([]);
	const list = ref<NoteEntity[]>([]);

	const total = ref<number>(0);

	async function getNoteInfo() {
		detail.value = await ApiNoteBookInfo(id);
	}

	/**
	 * 查询参数
	 */
	const query = ref({
		pageNo: 1,
		pageSize: 28,
		groupId: id,
	});

	/**
	 * 获取笔记详情列表
	 */
	async function getNotelList() {
		const data = await ApiNoteList(query.value);
		list.value = handleBodyText(data.list);
		total.value = data.total;
	}

	/**
	 * 转换
	 * @param block
	 */
	function convertHtml(block: any) {
		switch (block.type) {
			case 'header':
				return `<h${block.data.level}>${block.data.text}</h${block.data.level}>`;
			case 'paragraph':
				return `<p>${block.data.text}</p>`;
			case 'list':
				const listTag = block.data.style === 'ordered' ? 'ol' : 'ul';
				return `<${listTag}>${block.data.items.map((item: any) => `<li>${item.content}</li>`).join('')}</${listTag}>`;
			case 'image':
				return `<img src="${block.data.file.url}" alt="${block.data.caption}" style="max-width: 50%;margin: 5px 0">`;
			case 'table':
				return `<table>${block.data.content.map((row: any) => `<tr>${row.map((cell: any) => `<td>${cell}</td>`).join('')}</tr>`).join('')}</table>`;
			case 'code':
				return `<pre><code>${block.data.code}</code></pre>`;
			case 'inlineCode':
				return `<code>${block.data.code}</code>`;
			case 'delimiter':
				return `<hr>`;
			default:
				return '';
		}
	}

	/**
	 * 处理数据
	 * @param JsonList
	 */
	function handleBodyText(JsonList: NoteEntity[]) {
		return map(JsonList, (item: NoteEntity) => {
			let html = '';
			if (item?.body) {
				const body = JSON.parse(item?.body);

				html += map(body.blocks, (block: any) => convertHtml(block)).join('');
			}
			return { ...item, html };
		});
	}

	if (id) {
		getNoteInfo();
		getNotelList();
	}

	/**
	 * 防止无效提交 笔记本信息
	 */
	const editBook = ref({
		name: {
			is: false,
			newValue: null,
		},
		remark: {
			is: false,
			newValue: null,
		},
	});

	/**
	 * 获取编辑参数
	 */
	function getEditBookParams(): NoteBookDetailEntity {
		return {
			id,
			name: editBook.value.name.newValue || detail.value?.name,
			remark: editBook.value.remark.newValue || detail.value?.remark,
		};
	}

	/**
	 * 更新笔记本
	 */
	async function updateBookNote(params: NoteBookDetailEntity) {
		await ApiNoteBookUpdate(params);
		await getNoteInfo();
		Message.success('操作成功');
	}

	/**
	 * 更新笔记本名称
	 */
	async function updateNoteName() {
		if (editBook.value.name.newValue === '') {
			Message.error('请输入笔记名称');
			return;
		}
		if (editBook.value.name.newValue) {
			await updateBookNote(getEditBookParams());
			editBook.value.name.newValue = null;
		}

		editBook.value.name.is = false;
	}

	/**
	 * 更新笔记本备注
	 */
	async function updateNoteRemark() {
		if (editBook.value.remark.newValue != null) {
			await updateBookNote(getEditBookParams());
			editBook.value.remark.newValue = null;
		}

		editBook.value.remark.is = false;
	}

	/**
	 * 更新笔记本封面
	 */
	const { handleOnChange, handleOpen } = useUploadFile();

	handleOnChange(async (files: FileList, param: any) => {
		console.log(param);
		const os = await ApiUpload(fileToFormData(files[0]));
		await updateBookNote({ ...param, coverUrl: os.filename });
	});

	const noteListRef = ref<HTMLElement | null>(null);

	/**
	 * 滚动加载
	 */
	useInfiniteScroll(
		noteListRef,
		useThrottleFn(async () => {
			if (Math.ceil(total.value / query.value.pageSize) === query.value.pageNo) return;

			query.value.pageNo++;
			const data = await ApiNoteList(query.value);
			list.value.push(...handleBodyText(data.list));
		}, 4000),
		{ distance: 10 },
	);

	useBarAction('LeftBack', () => router.go(-1));

	const noteAddRef = useCompRef(NoteAdd);
	/**
	 * 添加笔记
	 */
	useBarAction('RightAdd', () => {
		noteAddRef.value?.open();
	});
</script>

<template>
	<section
		v-if="detail"
		class="detail h-full flex flex-row"
	>
		<div class="info w-[345px] border-r border-[#e7e9e8]">
			<div class="cover overflow-hidden p[10px] h-[200px] border-b border-[#e7e9e8]">
				<div class="relative w-full h-full">
					<div
						class="w-full h-full"
						@click.stop="handleOpen(detail)"
					>
						<a-image
							:preview="false"
							width="100%"
							height="100%"
							class="rounded-5px cursor-pointer border border-#e7e9e8"
							:src="FILE_PREVIEW + detail?.coverUrl"
						/>
					</div>
					<div class="absolute flex-center flex-col color-white pt-8px pb-5px justify-between text-center w-full left-0 right-0 bottom-0 m-auto bg-black/60 rounded-b-[5px]">
						<div class="w-full">
							<a-input
								placeholder="请输入笔记名称"
								:error="editBook.name.newValue == ''"
								:class="['detail-input w-80% ', editBook.name.is ? 'edit' : '', editBook.name.newValue === '' ? 'err' : '']"
								:show-word-limit="editBook.name.is"
								@blur="updateNoteName"
								@input="(v: any) => (editBook.name.newValue = v)"
								v-model="detail.name"
								@focus="() => $nextTick(() => (editBook.name.is = true))"
								:max-length="20"
							></a-input>
						</div>
						<time class="truncate text-12px">创建于 {{ detail?.createTime }}</time>
					</div>
				</div>
			</div>

			<div class="p[10px] overflow-auto">
				<div class="mb10px text-left font-700 text-14px">备注</div>
				<div class="color-[#999] leading-[20px] text-justify break-words">
					<a-textarea
						v-model="detail.remark"
						@input="(v: any) => (editBook.remark.newValue = v)"
						@blur="updateNoteRemark"
						placeholder="请输入备注"
						:max-length="250"
						show-word-limit
						class="remark-textarea"
					/>
				</div>
			</div>
		</div>

		<div class="content flex-1 p[10px] h-full">
			<template v-if="total > 0">
				<div class="pb-8px">
					<h2 class="text-14px font-700 bm-10px inline-block mr-8px">ALL</h2>
					<span class="text-12px color-#999 font-700">{{ total }}</span>
				</div>

				<div
					ref="noteListRef"
					class="list overflow-y-scroll h-[calc(100%-25px)]"
				>
					<a-grid
						:cols="{ xs: 1, sm: 2, md: 2, lg: 3, xl: 4, xxl: 4 }"
						:colGap="12"
						:rowGap="16"
					>
						<a-grid-item
							v-for="v in list"
							:key="v.id"
						>
							<div
								@click.stop="noteAddRef?.open(v)"
								class="h-300px flex flex-col border border-#e7e9e8 rounded-10px bg-#fcfcfc cursor-pointer hover:transition-shadow hover:duration-300 hover:shadow-[0_3px_10px_4px_#f2f1f1]"
							>
								<div class="p-10px h-[35px] truncate w-full font-700">{{ v.title }}</div>
								<div class="detail-body flex-1 pr-10px pl-10px overflow-auto scrollbar-hide!">
									<div
										class="overflow-x-hidden"
										v-html="v.html"
									></div>
								</div>
								<div class="px-10px border-t border-#e7e9e8 h-40px leading-40px color-#999 text-11px">最后更新: {{ v.createTime }}</div>
							</div>
						</a-grid-item>
					</a-grid>
				</div>
			</template>
			<a-empty
				class="mt-10%"
				v-else
			/>
		</div>

		<NoteAdd
			@ok="getNotelList"
			ref="noteAddRef"
		/>
	</section>
</template>

<style scoped lang="scss">
	.remark-textarea {
		height: 186px;

		:deep(.arco-textarea) {
			resize: none;
		}
	}

	.detail {
		&-input {
			background-color: transparent !important;
			cursor: text !important;

			:deep(.arco-input) {
				color: white !important;
				font-size: 13px;
				white-space: nowrap;
				text-align: center;
			}

			&.edit {
				:deep(.arco-input) {
					text-align: left;

					&::placeholder {
						color: red !important;
					}
				}
			}

			&.err {
				border-color: red;

				:deep(.arco-input) {
					color: red !important;
					text-align: left;

					&::placeholder {
						color: red !important;
					}
				}
			}

			:deep(.arco-input[disabled]) {
				-webkit-text-fill-color: white;

				&:hover {
					background: transparent !important;
				}
			}
		}
	}
</style>
